package com.ckx.aspect;

import com.alibaba.fastjson.JSON;
import com.ckx.annotation.SysLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 日子打印
 */
@Component
@Aspect
@Slf4j
public class LogAspect {

    @Pointcut("@annotation(com.ckx.annotation.SysLog)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public void logPrint(ProceedingJoinPoint joinPoint) throws Throwable {

        ServletRequestAttributes requestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {//为空就只进行执行时间输出
            execTime(joinPoint);
            return;
        }
        HttpServletRequest request = requestAttributes.getRequest();

        log.info("=================start=================");
        try {
            long startTime = System.currentTimeMillis();
            handleBefore(request, joinPoint);
            Object result = joinPoint.proceed();
            long executeTime = System.currentTimeMillis() - startTime;
            log.info("COST TIME         :{}ms", executeTime);//输出执行时间
            handleAfter(result);
        } finally {
            log.info("=================end=================" + System.lineSeparator());
        }

    }

    private void handleBefore(HttpServletRequest request, ProceedingJoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        SysLog sysLog = method.getAnnotation(SysLog.class);

        log.info("URL               : {}", request.getRequestURL());
        log.info("BusinessName      : {}", sysLog.businessName());
        log.info("HTTP Method       : {}", request.getMethod());
        log.info("Class Method      : {}.{}", methodSignature.getDeclaringTypeName(), method.getName());
        log.info("IP                : {}", request.getRemoteAddr());
        log.info("Request Args      : {}", JSON.toJSONString(joinPoint.getArgs()));

    }

    private void handleAfter(Object result) {
        log.info("Response          : {}", JSON.toJSONString(result));
    }

    private void execTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long executeTime = System.currentTimeMillis() - startTime;
        log.info("BusinessName      : {}", ((MethodSignature)joinPoint.getSignature()).getMethod()
                .getAnnotation(SysLog.class).businessName());
        log.info("COST TIME         :{}ms", executeTime);
    }

}
